

#import "SPReachabilityManager.h"
#import "SPReachability.h"

NSString *kSPConnectionStatusCurrentValueNotification = @"kSPConnectionStatusCurrentValue";
NSString *kSPConnectionStatusChangedNotification = @"kSPConnectionStatusChanged";

@interface SPReachabilityManager () <SPReachabilityDelegate>

@property (nonatomic) BOOL isListeningStarted;
@property (atomic) SPConnectionStatus currStatus;
@property (atomic) SPConnectionStatus prevStatus;
@property (nonatomic, strong) SPReachability *internetReachability;

@end

@implementation SPReachabilityManager

+ (SPReachabilityManager *)sharedInstance
{
    static SPReachabilityManager *__singleton__ = nil;
    @synchronized(self) {
        if (!__singleton__) {
            __singleton__ = [[SPReachabilityManager alloc] init];
        }
    }
    return __singleton__;
}

- (id)init
{
    self = [super init];
    if (self)
    {
        self.isListeningStarted = NO;
        self.prevStatus = kSPConnectionStatusUnknown;
        self.currStatus = kSPConnectionStatusUnknown;
        self.internetReachability = [SPReachability reachabilityWithHostName:@"api.ffan.com" delegate:self];
    }
    
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kSPConnectionStatusChangedNotification object:nil];
}

- (void)startListeningConnectionStatus
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (self.isListeningStarted == NO)
        {
            self.isListeningStarted = YES;
            [self.internetReachability startNotifier];
            [self updateReachability:self.internetReachability];
        }
    });
}

- (SPConnectionStatus)connStatus
{
    return self.currStatus;
}

- (SPConnectionStatus)previousConnectionStatus
{
    return self.prevStatus;
}

- (SPConnectionStatus)currentConnectionStatus
{
    return self.currStatus;
}

#pragma mark - delegate

- (void)reachabilityChanged:(SPReachability *)reachability
{
    if (reachability)
    {
        [self updateReachability:reachability];
    }
}

#pragma mark - update

- (void)refreshConnectionStatus
{
    if (!self.isListeningStarted)
        [self startListeningConnectionStatus];
    [self updateReachability:self.internetReachability];
}

- (void)updateReachability:(SPReachability *)reachability
{
    SPReachableStatus netStatus = [reachability currentReachabilityStatus];
    BOOL connectionRequired = [reachability connectionRequired];
    SPConnectionStatus connStatus = kSPConnectionStatusNone;
    if (!connectionRequired)
    {
        switch (netStatus)
        {
            case ReachableViaWWAN:
                connStatus = kSPConnectionStatusInternet;
                break;
            case ReachableViaWiFi:
                connStatus = kSPConnectionStatusWifi;
                break;
            default:
                break;
        }
    }
    
    // ignore if nothing changed
    if (self.currStatus == connStatus)
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:kSPConnectionStatusCurrentValueNotification object:@(connStatus)];
        return;
    }
    
    self.prevStatus = self.currStatus;
    self.currStatus = connStatus;
    
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kSPConnectionStatusChangedNotification object:@(connStatus)];
}

- (NSString *)connectionStatusString:(SPConnectionStatus)status
{
    switch (status)
    {
        case kSPConnectionStatusNone:
            return @"无网络连接";
        case kSPConnectionStatusWifi:
            return @"WiFi";
        case kSPConnectionStatusInternet:
            return @"蜂窝网络";
        default:
            return @"未知网络";
    }
}

@end
